package fuzion24.device.vulnerability.vulnerabilities;


import android.content.Context;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

import fuzion24.device.vulnerability.util.CPUArch;
import fuzion24.device.vulnerability.vulnerabilities.framework.graphics.GraphicBufferTest;
import fuzion24.device.vulnerability.vulnerabilities.framework.media.CVE_2015_6602;
import fuzion24.device.vulnerability.vulnerabilities.framework.media.CVE_2015_6608;
import fuzion24.device.vulnerability.vulnerabilities.framework.media.CVE_2015_6616;
import fuzion24.device.vulnerability.vulnerabilities.framework.media.StageFright;
import fuzion24.device.vulnerability.vulnerabilities.framework.serialization.OpenSSLTransientBug;
import fuzion24.device.vulnerability.vulnerabilities.framework.zip.ZipBug8219321;
import fuzion24.device.vulnerability.vulnerabilities.framework.zip.ZipBug9695860;
import fuzion24.device.vulnerability.vulnerabilities.framework.zip.ZipBug9950697;
import fuzion24.device.vulnerability.vulnerabilities.helper.SystemUtils;
import fuzion24.device.vulnerability.vulnerabilities.kernel.CVE_2011_1149;
import fuzion24.device.vulnerability.vulnerabilities.kernel.CVE_2013_6282;
import fuzion24.device.vulnerability.vulnerabilities.kernel.CVE_2014_3153;
import fuzion24.device.vulnerability.vulnerabilities.kernel.CVE_2014_4943;
import fuzion24.device.vulnerability.vulnerabilities.kernel.CVE_2015_3636;
import fuzion24.device.vulnerability.vulnerabilities.system.CVE20151528;
import fuzion24.device.vulnerability.vulnerabilities.system.CVE20153860;
import fuzion24.device.vulnerability.vulnerabilities.system.CVE_2016_0807;
import fuzion24.device.vulnerability.vulnerabilities.system.SamsungCREDzip;
import fuzion24.device.vulnerability.vulnerabilities.system.WeakSauce;

public class VulnerabilityOrganizer {

    private static final String TAG = "VulnerabilityOrganizer";

    private VulnerabilityOrganizer() {
    }

    //TODO: Maybe add dates to each of these and sort chronologically
    public static List<VulnerabilityTest> getTests(Context ctx){
        List<VulnerabilityTest> allTests = new ArrayList<>();
        allTests.add(new ZipBug9950697());
        allTests.add(new ZipBug8219321());
        allTests.add(new ZipBug9695860());
       // allTests.add(new JarBug13678484());
        allTests.add(new CVE_2013_6282());
        allTests.add(new CVE_2011_1149());
        allTests.add(new CVE_2014_3153());
        allTests.add(new CVE_2014_4943());
        //tests.add(new StumpRoot());
        allTests.add(new WeakSauce());
        allTests.add(new GraphicBufferTest());
        allTests.addAll(StageFright.getTests(ctx));
        allTests.add(new CVE_2015_6602());
        allTests.add(new OpenSSLTransientBug());
        allTests.add(new CVE_2015_3636());
        //tests.add(new ZergRush()); // Hide super old bugs?
        allTests.add(new SamsungCREDzip());
        allTests.add(new CVE_2015_6608());
        allTests.add(new CVE20151528());
        allTests.add(new CVE_2015_6616());
        allTests.add(new CVE20153860());
        allTests.add(new CVE_2016_0807());

        List<VulnerabilityTest> filteredTest = new ArrayList<>();
        String cpuArch1 = SystemUtils.propertyGet(ctx, "ro.product.cpu.abi");
        String cpuArch2 = SystemUtils.propertyGet(ctx, "ro.product.cpu.abi2");


        /*
            The logic here is:
              The test must support every architecture that the device lists
         */
        for(VulnerabilityTest vt : allTests){

            if(vt.getSupportedArchitectures() == null) {
                Log.d(TAG, "architectures is null for : " + vt.getCVEorID());
            }

            if(vt.getSupportedArchitectures().contains(CPUArch.ALL)){
                filteredTest.add(vt);
            } else {
                if(isArchitectureSupported(vt, cpuArch1) &&
                   isArchitectureSupported(vt, cpuArch2)){
                    filteredTest.add(vt);
                }
            }
        }
        return filteredTest;
    }

    private static boolean isArchitectureSupported(VulnerabilityTest vt, String architecture){
        if(architecture == null || architecture.equals("")) return true;

        for(CPUArch arch : vt.getSupportedArchitectures()){
            if(arch.getArch().equals(architecture)){
                return true;
            }
        }

        return false;
    }

}
